package com.neuedu.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.fastjson2.JSON;
import com.neuedu.model.Order;
import com.neuedu.model.Product;
import com.neuedu.model.User;
import com.neuedu.service.OrderService;
import com.neuedu.service.ProductServiceFeign;
import com.neuedu.service.StockServiceFeign;
import com.neuedu.service.UserServiceFeign;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

@Slf4j
@RestController
public class OrderController {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private OrderService orderService;
    @Autowired
    private DiscoveryClient discoveryClient;

    @Autowired
    private ProductServiceFeign productServiceFeign;

    @Autowired
    private UserServiceFeign userServiceFeign;

    @Autowired
    private StockServiceFeign stockServiceFeign;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;


    @RequestMapping("/order/product/{pid}")
    @SentinelResource(value = "queryProduct")
    public Order getOrderById(@PathVariable("pid") Integer pid){
        //查询下单商品信息
//        log.info("收到{}号商品下单请求,调用商品微服务查询此商品信息",pid);
//        Product product = restTemplate.getForObject("http://localhost:9010/product/" + pid, Product.class);
//        log.info("查询到商品信息，内容为{}",pid, JSON.toJSONString(product));
//        ServiceInstance serviceInstance = discoveryClient.getInstances("server-product").get(0);
//        Product product = restTemplate.getForObject("http://" + serviceInstance.getHost() + ":" +
//                serviceInstance.getPort() + "/product/" + pid,Product.class);

//        List<ServiceInstance> instances = discoveryClient.getInstances("service-product");
//        int index = new Random().nextInt(instances.size());
//        ServiceInstance serviceInstance = instances.get(index);
//        log.info("从nacos获得的地址为：{}", serviceInstance.getPort());
//        Product product = restTemplate.getForObject("http://" + serviceInstance.getHost() + ":" +
//                serviceInstance.getPort() + "/product/" + pid,Product.class);

       // Product product = restTemplate.getForObject("http://service-product/product/" + pid, Product.class);
        Product product = productServiceFeign.queryProductById(pid);
        if (product.getPid() == -1){
            Order order = new Order();
            order.setOid(-999L);
            order.setPname(product.getPname());
            return order;
        }


        //下单（创建订单）模拟测试用户，买了一件商品
        Order order = new Order();
        order.setPid(pid);
        order.setUid(1);
        order.setUsername("张三");
        order.setPname(product.getPname());
        order.setPprice(product.getPprice());
        order.setNumber(1);
//        rocketMQTemplate.convertAndSend("order-topic", order);
        orderService.addOrder(order);
        log.info("创建订单成功，订单信息为{}", JSON.toJSONString(order));
        return order;


    }
    @SentinelResource(value = "hot_queryoid")
    @RequestMapping("/order/query/{oid}")
    public Order queryOrderById(@PathVariable("oid") Long oid){
        log.info("收到订单编号：{}请求，调用订单查询方法：queryOrderById()", oid);
        Order order = orderService.queryOrderById(oid);
        log.info("订单查询成功，订单信息为：{}", JSON.toJSONString(order));
        return order;
    }
    @RequestMapping("/order/updatestatus/{oid}")
    public void updateOrderStatusById(@PathVariable("oid") Long oid){
        log.info("收到订单编号请求：{}，调用订单状态修改方法：updateOrderStatusById", oid);
        orderService.updateOrderStatus(oid);
        log.info("订单状态修改成功，订单信息为：{}", oid);

    }
    @RequestMapping("/order/queryproduct/{oid}")
    @SentinelResource(value = "queryProduct")
    public Product queryProduct(@PathVariable("oid") Long oid){
        log.info("收到编号{}的订单，调用订单查询方法：queryOrderById()", oid);
        Order order = orderService.queryOrderById(oid);
        if (order != null){
            Product product = productServiceFeign.queryProductById(order.getPid());
            log.info("订单查询成功，订单中的商品信息为{}", JSON.toJSONString(product));
            return product;
        }else {
            log.info("订单查询失败，订单编号无效");
            return null;
        }
    }
    @RequestMapping("/order/queryall/{oid}")
    public Map<String,Object> queryOrderForAllById(@PathVariable("oid") Long oid){
        log.info("收到订单编号：{} 请求，调用订单查询方法：queryOrderById()", oid);
        Map<String,Object> orderMap = new HashMap<>();
        Order order = orderService.queryOrderById(oid);
        orderMap.put("order", order);
        User user = userServiceFeign.queryUserById(order.getUid());
        orderMap.put("user", user);
        log.info("查询成功，所有信息为：{}", JSON.toJSONString(orderMap));
        return orderMap;
    }
    @RequestMapping("/order/msg")
    public String message() {
        return "这是授权规则测试";
    }
    int i = 0;

    @SentinelResource(value = "message-product",
            blockHandlerClass = OrderControllerBlockHandlerClass.class,
            blockHandler = "messageProductBlockHandler",
            fallbackClass = OrderControllerFallbackClass.class,
            fallback = "messageProductFallback"
    )

    @RequestMapping("/order/msgproduct/{str}")
    public String messageProduct(@PathVariable("str") String str) {
        log.info("参数信息：{}", str);
        if (++i % 3 == 0) {
            throw new RuntimeException("messageProduct()方法模拟异常");
        }
        return "OrderController: " + str;
    }
    public static String messageProductBlockHandler(String str, BlockException ex) {
        log.error("messageProductBlockHandler 服务限流或熔断异常，参数信息：{}，异常信息：{} ", str, ex);
        return "messageProductBlockHandler 服务限流或熔断异常，参数信息：" + str + "，异常信息：" + ex.getMessage();
    }

    public static String messageProductFallback(String str, Throwable t) {
        log.error("messageProductFallback 异常，参数信息：{}，异常信息：{} ", str, t);
        return "messageProductFallback 异常，参数信息：" + str + "，异常信息：" + t.getMessage();
    }



}
